#include <iostream>
#include <ctime>

#include "src/ga.hpp"
#include "src/pso.hpp"
#include "src/de.hpp"

const int GA_METHOD = 1;
const int PSO_METHOD = 2;
const int DE_METHOD = 3;

using namespace std;

void tip(int &index) {
    cout<<"select optimization algorithm ... "<<endl;
    vector<string> methods = {
            "Select a method by the number:",
            "1. Naive Genetic Algorithm (GA). ",
            "2. Naive Particle Swarm Optimization (PSO). ",
            "3. Naive Differential Evolution (DE). "
    };
    for (const auto& m : methods) {
        cout<<m<<endl;
    }
    cout<<"select number : ";
    cin>>index;
    cout<<"============= Optimizing by "<<methods[index]<<"============="<<endl;
}

int main() {
    clock_t start = clock();

    GA::BasicGA ga;
    PSO::BasicPSO pso;
    DE::BasicDE de;

    int METHOD = 1;
    tip(METHOD);

    for (int func_num = 1; func_num <= 30; ++func_num) {
        cout<<"working on func "<<func_num<<" ... "<<endl;
        switch (METHOD) {
            case GA_METHOD:
                ga.set_save_path("results\\GA\\" + to_string(func_num) + ".txt");
                ga.init(40, 10, 0.6, 0.02);
                ga.set_bounds(-100, 100);
                ga.execute(func_num, 10000, 10);
                break;
            case PSO_METHOD:
                pso.set_save_path("results\\PSO\\" + to_string(func_num) + ".txt");
                pso.init(40, 10, 0.9, 2.0, 2.0);
                pso.set_bounds(-100, 100);
                pso.execute(func_num, 10000, 10);
                break;
            case DE_METHOD:
                de.set_save_path("results\\DE\\" + to_string(func_num) + ".txt");
                de.init(40, 10, 0.8, 0.9);
                de.set_bounds(-100, 100);
                de.execute(func_num, 10000, 10);
                break;
            default:
                cout<<"method not set. "<<endl;

        }
    }

    cout<<"All done. cost time: "<<(double(clock()-start)/CLOCKS_PER_SEC > 100 ?
                          ceil(double(clock()-start)/CLOCKS_PER_SEC) : double(clock()-start)/CLOCKS_PER_SEC)<<"s."<<endl;
    return 0;
}

